package com.taskmanagement.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.taskmanagement.dto.AIStepResponse;
import com.taskmanagement.entity.Step;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service
@RequiredArgsConstructor
public class AIService {

    private final ChatModel chatModel;
    private final ObjectMapper objectMapper;

    private ChatClient chatClient;

    // 懒加载ChatClient
    private ChatClient getChatClient() {
        if (chatClient == null) {
            chatClient = ChatClient.builder(chatModel)
                    .defaultSystem(getSystemPrompt())
                    .build();
        }
        return chatClient;
    }

    /**
     * 生成步骤链 - 同步版本
     */
    @Cacheable(value = "step-chains", key = "#taskName + ':' + #requirements.hashCode()", unless = "#result.isEmpty()")
    @Retryable(
            retryFor = {Exception.class},
            maxAttempts = 3,
            backoff = @Backoff(delay = 1000, multiplier = 2)
    )
    public List<Step> generateStepChain(String taskName, String requirements) {
        log.info("开始生成步骤链 - 任务: {}, 需求长度: {}", taskName, requirements.length());

        try {
            String prompt = buildPrompt(taskName, requirements);

            String response = getChatClient()
                    .prompt()
                    .user(prompt)
                    .call()
                    .content();

            log.debug("AI响应: {}", response);

            return parseAIResponse(response);

        } catch (Exception e) {
            log.error("生成步骤链失败 - 任务: {}, 错误: {}", taskName, e.getMessage(), e);
            return generateFallbackSteps(taskName, requirements);
        }
    }

    /**
     * 生成步骤链 - 异步版本
     */
    @Async("taskExecutor")
    public CompletableFuture<List<Step>> generateStepChainAsync(String taskName, String requirements) {
        return CompletableFuture.supplyAsync(() -> generateStepChain(taskName, requirements));
    }

    /**
     * 智能优化已有步骤链
     */
    public List<Step> optimizeStepChain(List<Step> existingSteps, String feedback) {
        log.info("开始优化步骤链 - 现有步骤数: {}", existingSteps.size());

        try {
            String optimizationPrompt = buildOptimizationPrompt(existingSteps, feedback);

            String response = getChatClient()
                    .prompt()
                    .user(optimizationPrompt)
                    .call()
                    .content();

            return parseAIResponse(response);

        } catch (Exception e) {
            log.error("优化步骤链失败: {}", e.getMessage(), e);
            return existingSteps; // 返回原始步骤链
        }
    }

    /**
     * 根据进度动态调整步骤链
     */
    public List<Step> adjustStepChain(List<Step> currentSteps, String progressUpdate, String challenges) {
        log.info("开始调整步骤链 - 当前步骤数: {}", currentSteps.size());

        try {
            String adjustmentPrompt = buildAdjustmentPrompt(currentSteps, progressUpdate, challenges);

            String response = getChatClient()
                    .prompt()
                    .user(adjustmentPrompt)
                    .call()
                    .content();

            return parseAIResponse(response);

        } catch (Exception e) {
            log.error("调整步骤链失败: {}", e.getMessage(), e);
            return currentSteps;
        }
    }

    /**
     * 构建系统提示词
     */
    private String getSystemPrompt() {
        return """
            你是一个专业的项目管理专家和任务分解专家。你的任务是根据用户提供的任务名称和需求描述，
            生成详细、可执行的步骤链。
            
            请遵循以下原则：
            1. 步骤应该逻辑清晰，按照合理的时间顺序排列
            2. 每个步骤都应该有明确的可衡量的完成标准与自我/他者验证方式
            3. 考虑步骤之间的依赖关系
            4. 估算每个步骤的完成时间要合理
            5. 提供具体的执行建议和注意事项
            
            
            请以JSON格式返回结果，包含以下字段：
            - steps: 步骤列表
            - reasoning: 分解reasoning说明
            - total_estimated_days: 总预计完成天数
            
            每个步骤包含：
            - title: 步骤标题
            - description: 详细描述
            - order: 执行顺序
            - estimated_days: 预计完成天数
            - dependencies: 依赖的前置步骤序号列表
            - required_resources: 所需资源列表
            - success_criteria: 成功完成标准
            """;
    }

    /**
     * 构建用户提示词
     */
    private String buildPrompt(String taskName, String requirements) {
        PromptTemplate promptTemplate = new PromptTemplate("""
            请为以下任务生成详细的步骤链：
            
            **任务名称**: {taskName}
            
            **需求描述**: 
            {requirements}
            
            **特殊要求**:
            - 请根据任务的性质和复杂度合理分解步骤
            - 确保步骤具有可操作性和可衡量性
            - 考虑实际工作中可能遇到的挑战和风险
            - 如果是技术类任务，请包含测试和部署步骤
            - 如果是创意类任务，请包含创意发想和迭代优化步骤
            
            请返回JSON格式的结果。
            """);

        Map<String, Object> promptParameters = Map.of(
                "taskName", taskName,
                "requirements", requirements
        );

        return promptTemplate.render(promptParameters);
    }

    /**
     * 构建优化提示词
     */
    private String buildOptimizationPrompt(List<Step> existingSteps, String feedback) {
        StringBuilder stepsJson = new StringBuilder();
        for (Step step : existingSteps) {
            stepsJson.append(String.format(
                    "- %d. %s: %s%n",
                    step.getOrderNum(),
                    step.getTitle(),
                    step.getDescription()
            ));
        }

        PromptTemplate promptTemplate = new PromptTemplate("""
            请优化以下现有的步骤链：
            
            **现有步骤**:
            {existingSteps}
            
            **优化反馈**:
            {feedback}
            
            请根据反馈意见，对步骤链进行优化：
            - 调整步骤顺序
            - 合并或拆分步骤
            - 修改步骤描述
            - 调整时间估算
            - 增加遗漏的步骤
            - 删除不必要的步骤
            
            请返回优化后的完整步骤链（JSON格式）。
            """);

        Map<String, Object> promptParameters = Map.of(
                "existingSteps", stepsJson.toString(),
                "feedback", feedback
        );

        return promptTemplate.render(promptParameters);
    }

    /**
     * 构建调整提示词
     */
    private String buildAdjustmentPrompt(List<Step> currentSteps, String progressUpdate, String challenges) {
        StringBuilder stepsJson = new StringBuilder();
        for (Step step : currentSteps) {
            String status = step.getIsCompleted() ? "已完成" : "未完成";
            stepsJson.append(String.format(
                    "- %d. %s (%s): %s%n",
                    step.getOrderNum(),
                    step.getTitle(),
                    status,
                    step.getDescription()
            ));
        }

        PromptTemplate promptTemplate = new PromptTemplate("""
            请根据当前进度和遇到的挑战，调整以下步骤链：
            
            **当前步骤状态**:
            {currentSteps}
            
            **进度更新**:
            {progressUpdate}
            
            **遇到的挑战**:
            {challenges}
            
            请根据实际情况调整剩余步骤：
            - 基于已完成步骤的经验调整后续步骤
            - 针对遇到的挑战提供解决方案
            - 调整时间估算和资源需求
            - 增加必要的风险缓解步骤
            
            请返回调整后的完整步骤链（JSON格式），包括已完成和未完成的步骤。
            """);

        Map<String, Object> promptParameters = Map.of(
                "currentSteps", stepsJson.toString(),
                "progressUpdate", progressUpdate,
                "challenges", challenges
        );

        return promptTemplate.render(promptParameters);
    }

    /**
     * 解析AI响应
     */
    private List<Step> parseAIResponse(String response) {
        try {
            // 提取JSON部分
            String jsonContent = extractJsonFromResponse(response);

            AIStepResponse aiResponse = objectMapper.readValue(jsonContent, AIStepResponse.class);

            List<Step> steps = new ArrayList<>();
            LocalDate startDate = LocalDate.now();
            // 修改为使用 BigInteger 类型
            BigInteger dayOffset = BigInteger.ZERO;

            for (AIStepResponse.AIStepItem item : aiResponse.getSteps()) {
                Step step = new Step();
                step.setTitle(item.getTitle());
                step.setDescription(buildDetailedDescription(item));
                step.setOrderNum(item.getOrder());
                step.setIsCompleted(false);

                // 计算预期完成日期 - 需要将 BigInteger 转换为 int 用于 plusDays
                LocalDate expectedDate = startDate.plusDays(dayOffset.intValue());
                step.setExpectedEndDate(Date.from(expectedDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

                // 正确使用 BigInteger 的 add 方法进行计算
                if (item.getEstimatedDays() != null && item.getEstimatedDays().compareTo(BigInteger.ZERO) > 0) {
                    dayOffset = dayOffset.add(item.getEstimatedDays());
                } else {
                    // 使用 BigInteger.valueOf 创建值为 3 的 BigInteger
                    dayOffset = dayOffset.add(BigInteger.valueOf(3)); // 默认3天
                }

                steps.add(step);
            }

            log.info("成功解析AI响应，生成 {} 个步骤", steps.size());
            return steps;

        } catch (Exception e) {
            log.error("解析AI响应失败: {}", e.getMessage(), e);
            throw new RuntimeException("AI响应解析失败", e);
        }
    }

    /**
     * 从响应中提取JSON
     */
    private String extractJsonFromResponse(String response) {
        // 查找JSON开始和结束位置
        int jsonStart = response.indexOf('{');
        int jsonEnd = response.lastIndexOf('}');

        if (jsonStart == -1 || jsonEnd == -1 || jsonStart >= jsonEnd) {
            throw new RuntimeException("响应中未找到有效的JSON格式");
        }

        return response.substring(jsonStart, jsonEnd + 1);
    }

    /**
     * 构建详细描述
     */
    private String buildDetailedDescription(AIStepResponse.AIStepItem item) {
        StringBuilder description = new StringBuilder(item.getDescription());

        if (item.getSuccessCriteria() != null && !item.getSuccessCriteria().trim().isEmpty()) {
            description.append("\n\n完成标准：").append(item.getSuccessCriteria());
        }

        if (item.getRequiredResources() != null && !item.getRequiredResources().isEmpty()) {
            description.append("\n\n所需资源：").append(String.join("、", item.getRequiredResources()));
        }

        return description.toString();
    }

    /**
     * 生成兜底步骤链
     */
    private List<Step> generateFallbackSteps(String taskName, String requirements) {
        log.warn("使用兜底方案生成步骤链");

        List<Step> steps = new ArrayList<>();
        String[] stepTitles;
        String[] stepDescriptions;

        // 基于关键词的简单分类逻辑
        if (containsKeywords(requirements, "开发", "编程", "程序", "代码", "软件")) {
            stepTitles = new String[]{
                    "需求分析与规划", "技术方案设计", "核心功能开发",
                    "测试与调试", "优化与重构", "部署与上线"
            };
            stepDescriptions = new String[]{
                    "深入分析需求，制定详细的开发计划和里程碑",
                    "设计技术架构、选择技术栈、制定编码规范",
                    "按照设计方案实现核心业务功能",
                    "进行全面测试，修复发现的问题",
                    "优化代码性能，重构不合理的设计",
                    "部署到生产环境，确保系统稳定运行"
            };
        } else if (containsKeywords(requirements, "报告", "文档", "写作", "分析", "研究")) {
            stepTitles = new String[]{
                    "资料搜集与整理", "大纲制定", "内容撰写",
                    "审核修订", "格式美化", "最终定稿"
            };
            stepDescriptions = new String[]{
                    "收集相关资料、数据和参考文献",
                    "制定文档结构框架和内容大纲",
                    "按照大纲逐章节撰写内容",
                    "审核内容准确性，修订不当之处",
                    "统一格式，添加图表，美化排版",
                    "最终检查确认，形成定稿版本"
            };
        } else {
            stepTitles = new String[]{
                    "任务分析与规划", "资源准备", "执行第一阶段",
                    "中期检查与调整", "执行第二阶段", "总结与收尾"
            };
            stepDescriptions = new String[]{
                    "深入分析任务要求，制定详细执行计划",
                    "准备完成任务所需的各种资源和工具",
                    "按照计划开始执行任务的第一阶段",
                    "检查当前进展，根据实际情况调整计划",
                    "继续执行任务的后续阶段工作",
                    "完成最后收尾工作，总结经验教训"
            };
        }

        LocalDate startDate = LocalDate.now();
        for (int i = 0; i < stepTitles.length; i++) {
            Step step = new Step();
            step.setTitle(stepTitles[i]);
            step.setDescription(stepDescriptions[i]);
            step.setOrderNum(new BigInteger(String.valueOf(i + 1)));
            step.setIsCompleted(false);

            LocalDate expectedDate = startDate.plusDays(i * 4); // 每个步骤4天
            step.setExpectedEndDate(Date.from(expectedDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));

            steps.add(step);
        }

        return steps;
    }

    /**
     * 检查关键词
     */
    private boolean containsKeywords(String text, String... keywords) {
        String lowerText = text.toLowerCase();
        return Arrays.stream(keywords)
                .anyMatch(keyword -> lowerText.contains(keyword.toLowerCase()));
    }
}
